package com.ps.weedingjumper.controller;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.controllers.Controller;
import com.badlogic.gdx.controllers.ControllerListener;
import com.badlogic.gdx.controllers.Controllers;
import com.badlogic.gdx.controllers.PovDirection;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.ps.weedingjumper.model.Player;
import com.ps.weedingjumper.model.World;
import com.ps.weedingjumper.view.PlayerView;
import com.ps.weedingjumper.view.WorldView;

public class WorldController implements InputProcessor {

	private Player playerModel;
	private World worldModel;
	private PlayerView playerView;
	private WorldView worldView;
	private boolean playerJumping;
	private TiledMapTileLayer collisionLayer;

	
//	public static final float SPEED = 30f;
//	public static final float GRAVITY = 10f;
	public static final float SPEED = 250f;
	public static final float GRAVITY = 350f;
	public static final float FRICTION = 200f;
	
	public WorldController() {
		playerModel = new Player(0, 32, 16, 19);
		worldModel = new World(new TmxMapLoader().load("maps/weddingjumpermap1.tmx"));
		playerView = new PlayerView(playerModel);
		worldView = new WorldView(worldModel, playerView);
		collisionLayer = (TiledMapTileLayer) worldModel.getMap().getLayers().get(0);
		Gdx.input.setInputProcessor(this);
		ControllerListener l = new ControllerListener() {
			
			@Override
			public boolean ySliderMoved(Controller arg0, int arg1, boolean arg2) {
				System.out.println("ySliderMoved");
				return false;
			}
			
			@Override
			public boolean xSliderMoved(Controller arg0, int arg1, boolean arg2) {
				System.out.println("xSliderMoved");
				return false;
			}
			
			@Override
			public boolean povMoved(Controller arg0, int arg1, PovDirection arg2) {
				
				if (arg2.compareTo(PovDirection.east) == 0) {
					playerModel.getVelocity().x = 120;
				} else if (arg2.compareTo(PovDirection.west) == 0) {
					playerModel.getVelocity().x = -120;
				} else if (arg2.compareTo(PovDirection.center) == 0) {
					playerModel.getVelocity().x = 0;
				}
				
				return false;
			}
			
			@Override
			public void disconnected(Controller arg0) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void connected(Controller arg0) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public boolean buttonUp(Controller arg0, int arg1) {
				return false;
			}
			
			@Override
			public boolean buttonDown(Controller arg0, int arg1) {
				// TODO Magic Numbers
				switch (arg1) {
				case 0:
					if (!playerJumping) {
						playerModel.getVelocity().y = SPEED;
						playerJumping = true;				
					}
				default:
					break;
				}
				
				return true;
			}
			
			@Override
			public boolean axisMoved(Controller arg0, int arg1, float arg2) {
				// TODO Auto-generated method stub
//				if (arg1 == 1) {
//					System.out.println("axisMoved " + arg1 + " " + arg2);
//				}
				return false;
			}
			
			@Override
			public boolean accelerometerMoved(Controller arg0, int arg1, Vector3 arg2) {
				System.out.println("accelerometerMoved");
				return false;
			}
			
		};
		
		Controllers.addListener(l);
		
	}
	
	public void resize() {
		playerModel.setX(0);
		playerModel.setY(32);
	}
	
	public void update(float delta) {
		float playerPositionX = playerModel.getX();
		float playerPositionY = playerModel.getY();
		Vector2 playerVelocity = playerModel.getVelocity(); 
		
		playerVelocity.y -= GRAVITY * delta;
		
		if (playerVelocity.y > SPEED) {
			playerVelocity.y = SPEED;
		} else if (playerVelocity.y < -SPEED) {
			playerVelocity.y = -SPEED;
		}
		
		playerModel.setX(playerPositionX + (playerVelocity.x * delta));
		playerModel.setY(playerPositionY + (playerVelocity.y * delta));
		
		
		checkCollision(playerModel, playerPositionX, playerPositionY);
		
	}
	
	private void checkCollision(Player player, float oldX, float oldY) {
		boolean collisionX;
		boolean collisionY;
		int newXFoot = (int)(player.getX() / collisionLayer.getTileWidth());
		int newYFoot = (int)(player.getY() / collisionLayer.getTileHeight());
		int newYHead = (int)((player.getY() + 19) / collisionLayer.getTileHeight());
		int oldXFoot = (int)(oldX / collisionLayer.getTileWidth());
		int oldYFoot = (int)(oldY / collisionLayer.getTileHeight());
		int oldYHead = (int)((oldY + 19) / collisionLayer.getTileHeight());
		float normalisedOldXFoot = ((int)(oldX / collisionLayer.getTileWidth())) * collisionLayer.getTileWidth();
		float normalisedOldYFoot = ((int)(oldY / collisionLayer.getTileHeight())) * collisionLayer.getTileHeight();
		
		if (newXFoot < 0 || newYFoot < 0 || oldXFoot < 0 || oldYFoot < 0 || newYHead < 0) {
		} else {
			collisionY = collisionLayer.getCell(oldXFoot, newYFoot).getTile().getProperties().containsKey("blocked");
			collisionY |= (normalisedOldXFoot != oldX) ? collisionLayer.getCell(oldXFoot+1, newYFoot).getTile().getProperties().containsKey("blocked") : false;
			
			if (collisionY) {
				player.setY(((int) (oldY / collisionLayer.getTileHeight())) * collisionLayer.getTileHeight());
				playerJumping = false;
			}
			
			collisionY = collisionLayer.getCell(oldXFoot, newYHead).getTile().getProperties().containsKey("blocked");
			collisionY |= (normalisedOldXFoot != oldX) ? collisionLayer.getCell(oldXFoot+1, newYHead).getTile().getProperties().containsKey("blocked") : false;
			
			if (collisionY) {
				player.setY((((int) (oldY / collisionLayer.getTileHeight())) * collisionLayer.getTileHeight()) + 12);
				player.getVelocity().y *= (player.getVelocity().y > 0) ? -1 : 1 ;
			}
			
			collisionX  = collisionLayer.getCell(newXFoot, oldYFoot).getTile().getProperties().containsKey("blocked");
			collisionX |= collisionLayer.getCell(newXFoot + 1, oldYFoot).getTile().getProperties().containsKey("blocked");
			collisionX |= (normalisedOldYFoot != oldY) ? collisionLayer.getCell(newXFoot, oldYFoot + 1).getTile().getProperties().containsKey("blocked") : false;
			collisionX |= (normalisedOldYFoot != oldY) ? collisionLayer.getCell(newXFoot + 1, oldYFoot + 1).getTile().getProperties().containsKey("blocked") : false;
			collisionX |= (normalisedOldYFoot != oldY) ? collisionLayer.getCell(newXFoot, oldYHead).getTile().getProperties().containsKey("blocked") : false;
			collisionX |= (normalisedOldYFoot != oldY) ? collisionLayer.getCell(newXFoot + 1, oldYHead).getTile().getProperties().containsKey("blocked") : false;
			collisionX |= player.getX() < 0;
			
			if (collisionX) {	
				player.setX((int) ((oldX + 8) / collisionLayer.getTileWidth()) * collisionLayer.getTileWidth());
			}		
		}
		
	}
	
	public WorldView getWorldView() {
		return worldView;
	}
	
	public void setWorldView(WorldView worldView) {
		this.worldView = worldView;
	}
	
	public PlayerView getPlayerView() {
		return playerView;
	}
	
	public void setPlayerView(PlayerView playerview) {
		this.playerView = playerview;
	}

	@Override
	public boolean keyDown(int keycode) {
		// TODO Magic Numbers
		switch (keycode) {
		case Keys.RIGHT:
			playerModel.getVelocity().x = (Gdx.input.isKeyPressed(Keys.LEFT)) ? playerModel.getVelocity().x : 120;
			break;
		case Keys.LEFT:
			playerModel.getVelocity().x = (Gdx.input.isKeyPressed(Keys.RIGHT)) ? playerModel.getVelocity().x : -120;
			break;
		case Keys.UP:
			if (!playerJumping) {
				playerModel.getVelocity().y = SPEED;
//				playerJumping = true;				
			}
		default:
			break;
		}
		
		return true;
	}

	@Override
	public boolean keyUp(int keycode) {
		switch (keycode) {
		case Keys.RIGHT:
			playerModel.getVelocity().x = (Gdx.input.isKeyPressed(Keys.LEFT)) ? -120 : 0;
			break;
		case Keys.LEFT:
			playerModel.getVelocity().x = (Gdx.input.isKeyPressed(Keys.RIGHT)) ? 120 : 0;
			break;
		default:
			break;
		}
		
		return true;
	}

	@Override
	public boolean keyTyped(char character) {
		return false;
	}

	@Override
	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	@Override
	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
		return false;
	}

	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		return false;
	}

	@Override
	public boolean mouseMoved(int screenX, int screenY) {
		return false;
	}

	@Override
	public boolean scrolled(int amount) {
		return false;
	}
	
}
